import socket 
import threading
import time

# 全局变量：存储接收到的数据（格式：[(客户端地址, 数据), ...]）
received_data = []
# 电梯楼层
floor = [1,2,3]
devList = {
    "escalator":{
        "open":"01050000FF008C3A",
        "close":"010500000000CDCA",
        "down":"020F0000000201021F43",
        "up":"020F0000000201015F42",
        "none":"020F0000000201009E82",
        "1":"0206000000014839",
        "2":"0206000000020838",
        "3":"020600000003C9F8"
    },
    "gates":{
        "open":"01050000FF008C3A",
        "close":"010500000000CDCA",
    }
}

start_floor = 1

class GatController:
    def __init__(self, ip, port, timeout=5):
        self.ip = ip
        self.port = port
        self.timeout = timeout
        self.socket = None

    def connect(self):
        """建立TCP连接"""
        try:
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.socket.settimeout(self.timeout)
            self.socket.connect((self.ip, self.port))
            print(f"已连接到闸机：{self.ip}:{self.port}")
            return True
        except Exception as e:
            print(f"连接失败：{e}")
            self.socket = None
            return False

    def send_command(self, hex_command):
        """发送十六进制指令"""
        if not self.socket:
            print("未建立连接，请先调用connect()")
            return False
        try:
            # 将十六进制字符串转换为字节流
            command_bytes = bytes.fromhex(hex_command)
            self.socket.sendall(command_bytes)
            print(f"已发送指令：{hex_command}")
            
            # 接收闸机响应（可选，根据闸机是否返回响应调整）
            response = self.socket.recv(1024)
            if response:
                print(f"收到响应：{response.hex().upper()}")
            return True
        except Exception as e:
            print(f"发送失败：{e}")
            return False
        
    def send_text(self, text):
        """发送字符串"""
        if not self.socket:
            print("未建立连接，请先调用connect()")
            return False
        try:
            self.socket.sendall(text.encode('utf-8'))
            print(f"已发送指令：{text}")
            
            # 接收闸机响应（可选，根据闸机是否返回响应调整）
            response = self.socket.recv(1024)
            if response:
                print(f"收到响应：{response.hex().upper()}")
            return True
        except Exception as e:
            print(f"发送失败：{e}")
            return False

    def close(self):
        """关闭连接"""
        if self.socket:
            self.socket.close()
            print(f"tcp连接{self.ip}:{self.port}已关闭")
        self.socket = None

class linkDev():
    def __init__(self,host="192.168.1.8",port=4242):
        self.host = host
        self.port = port
        self.escalatorControl = GatController("192.168.1.107",4242)
        self.gatesControl = GatController("192.168.1.108",4242)
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # 允许端口复用
        self.server_socket.bind((self.host, self.port))
        self.escalator_thread = None
        self.start_floor = start_floor
        self.floor_requests = []
        self.running_flag = False
        self.devstate = {
            "escalator":{
                "state":"IDLE",
                "detall":"None",
                "floor":1,
                "door":"close",
            },"gates":{
                "state":"close"
            }
        }
        
    def setEscalator(self,state,timeout=1):
        if self.escalatorControl.connect():
            self.escalatorControl.send_command(devList["escalator"][state])
            with threading.Lock():
                self.devstate["escalator"]["state"] = "work"
                self.devstate["escalator"]["door"] = state
            time.sleep(timeout)
            return True
        return False

    def setGates(self,state,timeout=1):
        if self.gatesControl.connect():
            self.gatesControl.send_command(devList["gates"][state])
            with threading.Lock():
                self.devstate["gates"]["state"] = state
            time.sleep(timeout)
            return True
        return False
    
    def setDisplay(self,state,timeout=1):
        if self.setEscalator(state):
            if state in ["up","down","none"]:
                with threading.Lock():
                    self.devstate["escalator"]["state"] = "work"
                    self.devstate["escalator"]["detall"] = state
                    time.sleep(timeout)
            else:
                try:
                    with threading.Lock():
                        self.devstate["escalator"]["state"] = "work"
                        self.devstate["escalator"]["floor"] = int(state)
                except ValueError as err:
                    print(err)
            return True
        else:
            return False
        
    def escalator_move(self,address,floor):
        global received_data
        with threading.Lock():  # 避免多线程同时修改全局变量导致冲突
            received_data.append((address, floor))
        
    def escalator_loop(self):
        self.running_flag = True  # 启动时设置为True
        self.setDisplay('1')
        while(self.running_flag):
            try:
                time.sleep(0.2)
                # 获取电梯请求数据
                global received_data
                with threading.Lock():
                    for addr, data in received_data:
                        try:
                            if not int(data) in self.floor_requests:
                                if int(data) in floor:
                                    self.floor_requests.append(int(data))
                                    print(self.floor_requests)
                                    print('已接收到电梯请求数据')
                        except ValueError as err:
                            print(err)
                            print("未收到请求数据")
                    received_data = []
                # 处理电梯请求
                num = len(self.floor_requests)
                for i in range(num):
                    self.up_floor = self.floor_requests[0]
                    if self.up_floor > self.start_floor:
                        self.setDisplay('up')
                    elif self.up_floor < self.start_floor:
                        self.setDisplay('down')
                    self.start_floor = self.up_floor
                    self.setDisplay(str(self.start_floor))
                    self.setDisplay('none')
                    del self.floor_requests[0]
                with threading.Lock():
                    self.devstate["escalator"]["state"] = "IDLE"
                    self.devstate["escalator"]["detall"] = "none"
            except Exception as err:
                print(err)
        print("电梯控制器线程已退出")

    def close(self):
        print(f"TCP服务器已关闭，{self.host}:{self.port} ...")
        self.server_socket.close()
        self.gatesControl.close()
        self.escalatorControl.close()
        return True
    
    def getDevState(self):
        return self.devstate

    def handle_client(self,client_socket, client_address):
        """处理客户端连接，将数据存入全局变量"""
        print(f"新连接来自: {client_address}")
        try:
            while True:
                data = client_socket.recv(1024)
                if not data:
                    print(f"客户端 {client_address} 断开连接")
                    break
                # 解码数据
                decoded_data = data.decode('utf-8')
                print(f"从 {client_address} 收到: {decoded_data}")
                try:
                    if decoded_data == "go\n":
                        self.setGates("open")
                    elif decoded_data == "gc\n":
                        self.setGates("close")
                    elif decoded_data == "eo\n":
                        self.setEscalator("open")
                    elif decoded_data == "ec\n":
                        self.setEscalator("close")
                    elif decoded_data == "get\n":
                        print(self.devstate)
                    else:
                        self.escalator_move(client_address,decoded_data)
                except Exception as err:
                    print(err)
                # 发送确认信息
                response = f"服务器已收到: {decoded_data}"
                client_socket.sendall(response.encode('utf-8'))
        except Exception as e:
            print(f"处理客户端 {client_address} 时出错: {e}")
        finally:
            client_socket.close()

    def server_listen_loop(self,server_socket):
        """服务器监听循环（子线程中运行）"""
        try:
            while True:
                client_socket, client_address = server_socket.accept()
                client_thread = threading.Thread(
                    target=self.handle_client,
                    args=(client_socket, client_address)
                )
                client_thread.daemon = True
                client_thread.start()
        except Exception as e:
            print(f"监听线程出错: {e}")
        finally:
            server_socket.close()
            print("服务器套接字已关闭")["e"]["state"] = "close" 

    def start_tcp(self):
        """启动非阻塞TCP服务器"""
        try:
            if self.escalator_thread and self.escalator_thread.is_alive():
                print("电梯控制器线程已在运行")
                return self.escalator_thread
            print(f"电梯控制器已打开")
            self.escalator_thread = threading.Thread(
                target=self.escalator_loop,
                args=(),
                name="EscalatorControllerThread"
            )
            self.escalator_thread.daemon = True
            self.escalator_thread.start()
            return self.escalator_thread
        except Exception as e:
            print(f"电梯控制器启动失败: {e}")
            return None
        
    def start(self):
        try:
            self.start_tcp()
            self.server_socket.listen(5)
            print(f"TCP服务器已启动，监听 {self.host}:{self.port} ...")
            listen_thread = threading.Thread(
                target=self.server_listen_loop,
                args=(self.server_socket,)
            )
            listen_thread.daemon = True
            listen_thread.start()
            return listen_thread
        except Exception as e:
            print(f"服务器启动失败: {e}")
            self.close()
            return None
        
if __name__ == "__main__":
    link = linkDev()
    link.start()
    master = GatController("192.168.1.8",4242)
    # if master.connect():
    #     master.send_text("go\n")
    #     time.sleep(4)
    #     master.send_text("gc\n")
    while(1):
        time.sleep(1)